//$Id: GUI.java 242 2010-11-08 13:03:12Z edwardchuajh $

//Image credits:
// http://zooboingreview.blogspot.com/2009/12/seamless-texture-grass.html for Grass Texture


package builders;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;

import layout.TableLayout;


/**
 * This is the class for display all that is visual and awesome.
 * 
 * The <b> GUI </b>. <br />
 * 
 * Here is the description part for all the stuffs
 * 
 * @author Edward
 * @see layout.TableLayout
 * 
 * 
 */

public class GUI extends JFrame {


	private static final long serialVersionUID = 1L;
	
	/** Sets up the system path to images */
	private static String curDir = System.getProperty("user.dir");
	private static String imageDir = curDir + "\\src\\images\\";
	
	/** Holds all the GUI representation of the tiles */
	JLayeredPane[] tileLocations = new JLayeredPane[36];
	
	/** Main layer used for TableLayout and grids */
	JPanel framePane;
	
	/** Main layer used for TableLayout and grids */
	JLayeredPane mainPane;
	
	/** Full-screen layer used for splash screen */
	JLayeredPane splashScreen;
	
	/** Central area to display game progress, notification and player stats */
    JPanel displayArea;
    
    /** Bar area to display notification */
    JLayeredPane notificationPanel;
    
    /** Text area to display notification */
    JLabel notificationLabel;
    
    /** Panel to display player stats */
    JPanel playerStats;
    
    /** Button for dice roll */
    JButton rollDie;
    
    /** Array for dice roll */
    int steps = 0;
    
    /** Array for dice timer */
    Timer timer;
    
    /** Array for dice images */
    ImageIcon[] diceImages = new ImageIcon[6];
    
    /** Random Generator for dice images */
    Random randomGenerator = new Random();
    
    /** Set total number of players */
	final int totalPlayers = 4;
    
    /** Initialize player pieces */
    JLabel[] playerPieces = new JLabel[totalPlayers];
    
    /** Initialize current number of players */
    int currentNumberOfPlayers;
    
    /** Initialize players */
    ArrayList<Player> Players;
	
    /** GameState */
    GameState gameState;
    
    /** Logic */
    Logic logic = new Logic();
    
	
    
    /**
	 * The main method does cooks everything together and stuffs it
	 * to your screen.
	 *  
	 * @param args This is usually empty
	 * 
	 */
    public static void main(String[] args) {
		
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				GUI thisClass = new GUI();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		        thisClass.setResizable(true);
				thisClass.setVisible(true);			
			}
			
				
		});
	}
    
    /**
     * This methods is called each time the frame is resized, to maintain aspect ratio
     */
	public void resizeFrame() {
		
//		int frameWidth = this.getWidth();
		int frameHeight = this.getHeight();
		
		double ratio;
		
		ratio = 1.25; // (1000 / 800)
		
		int newHeight = frameHeight;
		int newWidth = (int) (frameHeight * ratio);
		
		this.setSize(newWidth, newHeight);		
		
	}

    
	
    /**
	 * This is the default constructor
	 */
	public GUI() {
		super();
		initialize();
		
		//Keeps aspect ratio of game during resizing
		this.addComponentListener(new ComponentAdapter() {

			public void componentResized(ComponentEvent evt) {
					resizeFrame();
			}
		});
	}
	
	
	/**
	 * This is the method to initialize GameState, Logic
	 */
	private void initialize() {
		
		//Game initialization code
				
		/** Set full game size */
		this.setSize(1050, 840);
		
		/** Sets Title */
		this.setTitle("Builders - The Board Game");
		
		//Initialize gameState
		gameState = logic.initialise();
		
		/** Creates all the GUI representations of the tiles */
		squareFactory();
		
		/** Place mainPane into the frame */
		this.setContentPane(getFramePane());
		
		//Initialize die roll array
		for(int i=0; i<6; i++) {
			
			diceImages[i] = new ImageIcon(imageDir + "dice" + (i+1) + ".png");
			
		}
		
		update(gameState);
		
	}
	
	
	/*****************************************************
	/*   GUI Components Singletons           
	/*   
	/*   e.g. getMainPane()
	/*****************************************************/
	
	/**
	 * This is the method initializes and returns the menu bar
	 */
	private JPanel getFramePane() {
		
		if(framePane == null) {
			
			framePane = new JPanel();
						
//			double b = 10;
			double f = TableLayout.FILL;
	        double p = TableLayout.PREFERRED;
			
			double size[][] =
            {{f},
			 {p, f}};

			framePane.setLayout(new TableLayout(size));
			
			framePane.add(getMenu(), "0, 0");
			framePane.add(getMainPane(), "0, 1");
			
			
		}
		
		return framePane;
		
	}
	
	/**
	 * This is the method initializes and returns the menu bar
	 */
	private JMenuBar getMenu() {

		//Set up menu items
		JMenuBar menuBar = new JMenuBar();
		JMenuItem menuItem;
		
		JMenu menu = new JMenu("Game Options");
		menu.setMnemonic(KeyEvent.VK_A);
		
		JMenu menu2 = new JMenu("Help");
		menu2.setMnemonic(KeyEvent.VK_H);
		
		menuItem = new JMenuItem("New Game", KeyEvent.VK_N);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));	
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				int n;
				
				//Check if mode is splash or new game
				if(gameState.getGameMode() == GameState.GameMode.NEW_GAME || gameState.getGameMode() == GameState.GameMode.SPLASH_SCREEN) {
					
					n = 1;					
					
				} else {
				
				
					//Start new game
					n = JOptionPane.showConfirmDialog(
					    getParent(),
					    "Do you wish to save before starting new game?",
					    "New Game",
					    JOptionPane.YES_NO_CANCEL_OPTION);
				
				}
			
				if(n == 1) { //New game without saving
					gameState = logic.execute(new Message(GameState.GameMode.NEW_GAME, null));			
					update(gameState);
				} else if (n == 0) { //Save game then new game
					
					//Save game
					String filename = File.separator+"tmp";
					JFileChooser fc = new JFileChooser(new File(filename));

					// Show save dialog; this method does not return until the dialog is closed
					fc.showSaveDialog(getParent());
					File selFile = fc.getSelectedFile();
					
					if (selFile != null) {
						
						String[] args = new String[1];
						args[0] = selFile.getAbsolutePath();
						
						gameState = logic.execute(new Message(GameState.GameMode.SAVE_GAME, args));
						
						update(gameState);
						
						gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
						
						JOptionPane.showMessageDialog(getParent(), "Game saved successfully! Click OK to start new game.");
						
						gameState = logic.execute(new Message(GameState.GameMode.NEW_GAME, null));			
						update(gameState); //New game after saving
					}	
					
				}
				
			}
		});
		menu.add(menuItem);
		
		menuItem = new JMenuItem("Save Game", KeyEvent.VK_S);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {

				
				//Check if mode is splash or new game
				if(gameState.getGameMode() == GameState.GameMode.NEW_GAME || gameState.getGameMode() == GameState.GameMode.SPLASH_SCREEN) {
					
					JOptionPane.showMessageDialog(getParent(), "Please start a game before attempting to save.");				
					
				} else {
				

					//Save game
					String filename = File.separator+"tmp";
					JFileChooser fc = new JFileChooser(new File(filename));
	
					// Show save dialog; this method does not return until the dialog is closed
					fc.showSaveDialog(getParent());
					File selFile = fc.getSelectedFile();
					
					if (selFile != null) {
						
						String[] args = new String[1];
						args[0] = selFile.getAbsolutePath();
						
						gameState = logic.execute(new Message(GameState.GameMode.SAVE_GAME, args));
						
						update(gameState);
						
						gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
						
						JOptionPane.showMessageDialog(getParent(), "Game saved successfully!");
						
						update(gameState);	
					}
				
				}
				
			}
		});
		menu.add(menuItem);
		
		menuItem = new JMenuItem("Load Game", KeyEvent.VK_L);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Load game
				String filename = File.separator+"tmp";
				JFileChooser fc = new JFileChooser(new File(filename));

				// Show open dialog; this method does not return until the dialog is closed
				fc.showOpenDialog(getParent());
				File selFile = fc.getSelectedFile();
				
				if (selFile != null) {
					
					String[] args = new String[1];
					args[0] = selFile.getAbsolutePath();
					
					gameState = logic.execute(new Message(GameState.GameMode.LOAD_GAME, args));
					
					gameState = logic.execute(new Message(GameState.GameMode.RESUME, args));
					
					displayArea.removeAll();
					
					
					//Rebuild tile data and repaint
					resetMainPane();
					
					//Reset the main panes
					getFramePane().removeAll();
					getFramePane().repaint();
					
					getFramePane().add(getMenu(), "0, 0");
					getFramePane().add(getMainPane(), "0, 1");
					
					displayArea.repaint();
					
					//Initialize player pieces
					Players = gameState.getPlayers();
					
					currentNumberOfPlayers = Players.size();
					
					for (int i=0; i < currentNumberOfPlayers; i++) {					
						playerPieces[i] = new JLabel(new ImageIcon(imageDir + Players.get(i).getPieceFileName()));
							tileLocations[Players.get(i).getPiecePosition()].add(playerPieces[i]);
					}
					
					update(gameState);

				}			
				
			}
		});
		menu.add(menuItem);
		
		menuItem = new JMenuItem("Exit Game", KeyEvent.VK_X);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK));
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Exit game
				int n = JOptionPane.showConfirmDialog(
					    getParent(),
					    "Do you wish to save before exiting?",
					    "Save Game",
					    JOptionPane.YES_NO_CANCEL_OPTION);
			
				if(n == 1) { //Exit without saving
					System.exit(0);
				} else if (n == 0) { //Save game then exit
					
					//Save game
					String filename = File.separator+"tmp";
					JFileChooser fc = new JFileChooser(new File(filename));

					// Show save dialog; this method does not return until the dialog is closed
					fc.showSaveDialog(getParent());
					File selFile = fc.getSelectedFile();
					
					if (selFile != null) {
						
						String[] args = new String[1];
						args[0] = selFile.getAbsolutePath();
						
						gameState = logic.execute(new Message(GameState.GameMode.SAVE_GAME, args));
						
						update(gameState);
						
						gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
						
						JOptionPane.showMessageDialog(getParent(), "Game saved successfully! Click OK to exit.");
						
						System.exit(0); //Exit game after saving
					}	
					
				}
				
			}
		});
		menu.add(menuItem);
		
		menuItem = new JMenuItem("How To Play", KeyEvent.VK_H);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				displayHelp();
				
			}
		});
		menu2.add(menuItem);
		
		menuItem = new JMenuItem("Building List", KeyEvent.VK_B);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK));
		menuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				GameState.GameMode gameMode = gameState.getGameMode();
						
				if(gameMode != GameState.GameMode.SPLASH_SCREEN && gameMode != GameState.GameMode.INITIALIZE && gameMode != GameState.GameMode.NEW_GAME) {
					modeBuildList();
				} else {
					JOptionPane.showMessageDialog(getParent(), "Please start a game to begin viewing buildings.");			
				}
				
				
			}
		});
		menu2.add(menuItem);
		
		
		menuBar.add(menu);
		menuBar.add(menu2);
		
		return menuBar;
	
	}
	
	/**
	 * This is the method initializes and returns the splashScreen
	 */
	private void displayHelp() {
		
		String help = new String();
		
		help = "<HTML>";
		help = help + "<b><u><font size='+1'>HOW TO PLAY BUILDERS</font></u></b><br><br>";
		help = help + "<b>Objective</b>:<br><ul><li>To be the first to build EIGHT buildings, or achieve " + gameState.getWinningCondition() + " building points.</li><br>";
		help = help + "<li>In the event of a tie, the player with higher points will win.</li></ul>";
		help = help + "<b>Instructions:</b><br><ul><li>Click on ROLL DIE to roll the dice to obtain activity points.<br>Then, click on a tile you wish to move to.</li><br>";
		help = help + "<li>ONE activity point will be deducted per tile moved after first tile.<br>Remaining activity points will be used to 'work' the tile.</li><br>";
		help = help + "<li>For example: You landed on a MUD (3X) tile with 2 activity points left,<br>you will obtain 2 x 3 = 6 MUD resources.</li><br>";
		help = help + "<li>Collect resources, head back to your homebase and START BUILDING!</li><br>";
		help = help + "<li>Go to <b>HELP</b> to see list of buildings available.</li><br></ul>";
		help = help + "</HTML>";
		
		
		JOptionPane.showMessageDialog(getParent(), help);
		
		
	}
	
	
	/**
	 * This is the method initializes and returns the splashScreen
	 */
	private JLayeredPane getSplashScreen() {
		if (splashScreen == null) {
			
			final ImageIcon icon = new ImageIcon(imageDir + "splash.jpg");
			splashScreen = new JLayeredPane() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
			
			splashScreen.setPreferredSize(new Dimension(1000,800));
			splashScreen.setBounds(0, 0, 1000,800);
			
			double size[][] =
            {{TableLayout.FILL, 160, 10, 160, TableLayout.FILL},
			 {TableLayout.FILL, 60, 50}}; 

			splashScreen.setLayout(new TableLayout(size));
			
			Border bdr = BorderFactory.createLineBorder(Color.black);
			splashScreen.setBorder(bdr);	
			
			//Option buttons
			JButton newGameButton = new JButton(new ImageIcon(imageDir + "newgame.png"));
			
			newGameButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					//Start new game
					gameState = logic.execute(new Message(GameState.GameMode.NEW_GAME, null));
					update(gameState);
					
				}
			});
			
			
			JButton loadGameButton = new JButton(new ImageIcon(imageDir + "loadgame.png"));
			
			loadGameButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					//Load game
					String filename = File.separator+"tmp";
					JFileChooser fc = new JFileChooser(new File(filename));

					// Show open dialog; this method does not return until the dialog is closed
					fc.showOpenDialog(getParent());
					File selFile = fc.getSelectedFile();
					
					if (selFile != null) {
						
						String[] args = new String[1];
						args[0] = selFile.getAbsolutePath();
						
						gameState = logic.execute(new Message(GameState.GameMode.LOAD_GAME, args));
						
						gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
						
						displayArea.removeAll();
						
						
						//Rebuild tile data and repaint
						resetMainPane();
						
						//Reset the main panes
						getFramePane().removeAll();
						getFramePane().repaint();
						
						getFramePane().add(getMenu(), "0, 0");
						getFramePane().add(getMainPane(), "0, 1");
						
						displayArea.repaint();
						
						
						
						//Initialize player pieces
						Players = gameState.getPlayers();
						
						currentNumberOfPlayers = Players.size();
						
						for (int i=0; i < currentNumberOfPlayers; i++) {					
							playerPieces[i] = new JLabel(new ImageIcon(imageDir + Players.get(i).getPieceFileName()));
								tileLocations[Players.get(i).getPiecePosition()].add(playerPieces[i]);
						}
						
						update(gameState);

					}
					
				}
			});
			
			splashScreen.add(newGameButton, "1,1");
			splashScreen.add(loadGameButton, "3,1");
	
		
		}
		
		return splashScreen;
	}
	
	/**
	 * This is the method initializes and returns the mainPane
	 */
	private JLayeredPane getMainPane() {
		if (mainPane == null) {
			
			//Adds background image ^^[e]^^
			final ImageIcon icon = new ImageIcon(imageDir + "grass_1000x800.jpg");
			mainPane = new JLayeredPane() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
			
			mainPane.setPreferredSize(new Dimension(1000,800));
			mainPane.setBounds(0, 0, 1000,800);
			
			
			double size[][] =
            {{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1},
			 {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}}; // Sets up table with 10x10 grid at 10% each with menubar at top^^[e]^^

			mainPane.setLayout(new TableLayout(size));

			//Populate tiles - yes, its a nightmare but TableLayout cannot take in a counter as input			
			//                 But at least we can now easily set which tile goes where without having
			//                 to perform mathematical jujitsu. <]^^[e]^^
			
			//Top tiles
			mainPane.add(tileLocations[0], "0, 0");
			mainPane.add(tileLocations[1], "1, 0");
			mainPane.add(tileLocations[2], "2, 0");
			mainPane.add(tileLocations[3], "3, 0");
			mainPane.add(tileLocations[4], "4, 0");
			mainPane.add(tileLocations[5], "5, 0");
			mainPane.add(tileLocations[6], "6, 0");
			mainPane.add(tileLocations[7], "7, 0");
			mainPane.add(tileLocations[8], "8, 0");
			mainPane.add(tileLocations[9], "9, 0");
			
			//Right tiles
			mainPane.add(tileLocations[10], "9, 1");
			mainPane.add(tileLocations[11], "9, 2");
			mainPane.add(tileLocations[12], "9, 3");
			mainPane.add(tileLocations[13], "9, 4");
			mainPane.add(tileLocations[14], "9, 5");
			mainPane.add(tileLocations[15], "9, 6");
			mainPane.add(tileLocations[16], "9, 7");
			mainPane.add(tileLocations[17], "9, 8");
					
			//Bottom tiles
			mainPane.add(tileLocations[18], "9, 9");
			mainPane.add(tileLocations[19], "8, 9");
			mainPane.add(tileLocations[20], "7, 9");
			mainPane.add(tileLocations[21], "6, 9");
			mainPane.add(tileLocations[22], "5, 9");
			mainPane.add(tileLocations[23], "4, 9");
			mainPane.add(tileLocations[24], "3, 9");
			mainPane.add(tileLocations[25], "2, 9");
			mainPane.add(tileLocations[26], "1, 9");
			mainPane.add(tileLocations[27], "0, 9");
			
			//Left tiles
			mainPane.add(tileLocations[28], "0, 8");
			mainPane.add(tileLocations[29], "0, 7");
			mainPane.add(tileLocations[30], "0, 6");
			mainPane.add(tileLocations[31], "0, 5");
			mainPane.add(tileLocations[32], "0, 4");
			mainPane.add(tileLocations[33], "0, 3");
			mainPane.add(tileLocations[34], "0, 2");
			mainPane.add(tileLocations[35], "0, 1");	
			
			//Populate display area	
			mainPane.add(getDisplayArea(), "1, 1, 8, 8");
			
		}
		
		return mainPane;
		
	}
	
	/**
	 * This is the method resets the main pane
	 */
	private void resetMainPane() {
		
		if(mainPane != null) {
		
			mainPane.removeAll();
			
			//Reset tile data
			squareFactory();
			
			//Top tiles
			mainPane.add(tileLocations[0], "0, 0");
			mainPane.add(tileLocations[1], "1, 0");
			mainPane.add(tileLocations[2], "2, 0");
			mainPane.add(tileLocations[3], "3, 0");
			mainPane.add(tileLocations[4], "4, 0");
			mainPane.add(tileLocations[5], "5, 0");
			mainPane.add(tileLocations[6], "6, 0");
			mainPane.add(tileLocations[7], "7, 0");
			mainPane.add(tileLocations[8], "8, 0");
			mainPane.add(tileLocations[9], "9, 0");
			
			//Right tiles
			mainPane.add(tileLocations[10], "9, 1");
			mainPane.add(tileLocations[11], "9, 2");
			mainPane.add(tileLocations[12], "9, 3");
			mainPane.add(tileLocations[13], "9, 4");
			mainPane.add(tileLocations[14], "9, 5");
			mainPane.add(tileLocations[15], "9, 6");
			mainPane.add(tileLocations[16], "9, 7");
			mainPane.add(tileLocations[17], "9, 8");
					
			//Bottom tiles
			mainPane.add(tileLocations[18], "9, 9");
			mainPane.add(tileLocations[19], "8, 9");
			mainPane.add(tileLocations[20], "7, 9");
			mainPane.add(tileLocations[21], "6, 9");
			mainPane.add(tileLocations[22], "5, 9");
			mainPane.add(tileLocations[23], "4, 9");
			mainPane.add(tileLocations[24], "3, 9");
			mainPane.add(tileLocations[25], "2, 9");
			mainPane.add(tileLocations[26], "1, 9");
			mainPane.add(tileLocations[27], "0, 9");
			
			//Left tiles
			mainPane.add(tileLocations[28], "0, 8");
			mainPane.add(tileLocations[29], "0, 7");
			mainPane.add(tileLocations[30], "0, 6");
			mainPane.add(tileLocations[31], "0, 5");
			mainPane.add(tileLocations[32], "0, 4");
			mainPane.add(tileLocations[33], "0, 3");
			mainPane.add(tileLocations[34], "0, 2");
			mainPane.add(tileLocations[35], "0, 1");	
			
			//Populate display area	
			mainPane.add(getDisplayArea(), "1, 1, 8, 8");
			
			mainPane.repaint();
			
		}
		
	}
	
	/**
	 * This is the method initializes and returns the displayArea
	 */
	private JPanel getDisplayArea() {
		if (displayArea == null) {
			
			displayArea = new JPanel();
			//displayArea.setLayout(new GridLayout(3, 3));
			displayArea.setBackground(Color.LIGHT_GRAY);
			displayArea.setOpaque(false);
			double size[][] =
            {{0.2, 0.2, 0.2, 0.2, 0.2},
			 {TableLayout.FILL, 0.2, 0.2, 60, 100}}; //

			displayArea.setLayout(new TableLayout(size));
			
		}
		return displayArea;
	}
	
	private JLabel getNotificationLabel() {
		
		if(notificationLabel == null) {
			
			//Adds background image ^^[e]^^
			final ImageIcon icon = new ImageIcon(imageDir + "notification.png");
			notificationLabel = new JLabel() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
			
			Border bdr = BorderFactory.createEmptyBorder(10, 20, 10, 10);
			notificationLabel.setBorder(bdr);
			
		}
		
		return notificationLabel;
		
	}
	
	private JButton getRollDie() {
		
		if(rollDie == null) {
			
			
			rollDie = new JButton("ROLL DIE");
			rollDie.setIcon(diceImages[randomGenerator.nextInt(6)]);

		}
		
		return rollDie;
	}
	
	private JPanel getPlayerStats() {
		
		if(playerStats == null) {
			
			playerStats = new JPanel();
			playerStats.setOpaque(false);
			
			playerStats.setLayout(new GridLayout(1, 4));
			
		}
		
		return playerStats;
		
	}
		

	/*****************************************************
	/*   Helper Methods           
	/*   
	/*   e.g. initialization methods
	/*****************************************************/
	
	
	
	/**
	 * This is the method initializes all the tiles and stores in tileLocations[]
	 */
	public void squareFactory() {
		
		int totalTiles = 36;
		
		for(int i=0;i<totalTiles;i++) {
			
			//String tileFileName = new String(gameState.getTileManager().getTileImageBG(i));
			String tileFileName = gameState.getTileManager().squareToTile(i).getImageFile();
		
			final ImageIcon icon= new ImageIcon(imageDir + tileFileName);
			
			JLayeredPane square = new JLayeredPane() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
					
			square.setLayout(new GridLayout(4, 1));
	        
	        square.setPreferredSize(new Dimension(100,80));	
	        square.setBounds(0, 0, 100, 80);
	        
	        //No border for corner tiles
	        if (i % 9 != 0) {
		       Border bdr = BorderFactory.createLineBorder(Color.black);    
		       square.setBorder(bdr);
	        }
	        
	       // square.add(tileBG, 10); //Adds to depth 10 ^^[e]^^
	        
	        tileLocations[i] = square;
			
		}
		
	}
	
	/**
	 * This is the method updates the player's statistics
	 */
	public void updatePlayerStats() {
		
		getPlayerStats().removeAll();
		getPlayerStats().repaint();
		
		for(int i=0; i < currentNumberOfPlayers; i++) {
			
			Player p = Players.get(i);
		
			final ImageIcon icon = new ImageIcon(imageDir + "playerstat.png");
			JPanel indivPlayer = new JPanel() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
			
			indivPlayer.setLayout(new GridLayout(9,1));
			indivPlayer.setOpaque(false);
			
			Border bdr = BorderFactory.createEmptyBorder(15, 15, 15, 15);
			indivPlayer.setBorder(bdr);
			
			//Add in name and resources
			indivPlayer.add( new JLabel(new ImageIcon(imageDir + p.getPieceFileName())));
			indivPlayer.add( new JLabel("<HTML><B><U><FONT SIZE='+1'>" + p.getName() + "</FONT></U></B></HTML>") );
			indivPlayer.add( new JLabel("Cement: " + p.getCurrentResourceAmount(Player.Resource.CEMENT)) );
			indivPlayer.add( new JLabel("Brick: " + p.getCurrentResourceAmount(Player.Resource.BRICK)) );
			indivPlayer.add( new JLabel("Mud: " + p.getCurrentResourceAmount(Player.Resource.MUD)) );
			indivPlayer.add( new JLabel("Glass: " + p.getCurrentResourceAmount(Player.Resource.GLASS)) );
			indivPlayer.add( new JLabel("Dung: " + p.getCurrentResourceAmount(Player.Resource.DUNG)) );
			indivPlayer.add( new JLabel("Sand: " + p.getCurrentResourceAmount(Player.Resource.SAND)) );
			indivPlayer.add( new JLabel("Points: " + p.getPointsAccumulated() + "/" + gameState.getWinningCondition()));
			
			getPlayerStats().add(indivPlayer);
			
			
		}
		
		//Need to pad out the empty players
		for(int i=0;i < totalPlayers - currentNumberOfPlayers; i++) {
			
			final ImageIcon icon = new ImageIcon(imageDir + "playerstat.png");
			JPanel indivPlayer = new JPanel() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				protected void paintComponent(Graphics g)
				{
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					g.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g);
				}
				
			};
			
			indivPlayer.setLayout(new GridLayout(7,1));
			indivPlayer.setOpaque(false);
			
			getPlayerStats().add(indivPlayer);
			
		}
		
	}
	
	
	 /**
	 * The method which updates the GUI depending on GameState's current mode
	 * 
	 * @param GameState The current game state
	 * 
	 */
	
	public void update(GameState g) {
		
		gameState = g;
		GameState.GameMode gameMode = gameState.getGameMode();

		// Update game state
		// Make sure MODE is not SPLASH_SCREEN or NEW_GAME
		// If not, then update player positions
				
		if(gameMode != GameState.GameMode.SPLASH_SCREEN && gameMode != GameState.GameMode.INITIALIZE) {
			
			//Clear all tiles
			
			for (int i=0; i<36; i++) {
				
				JLayeredPane tile = tileLocations[i];
				
				tile.removeAll();
				
				if (i % 9 != 0) {
					//Add back the tile story
					String tileStory = gameState.getTileManager().squareToTile(i).getNameOfTile();
					tileStory = tileStory.toUpperCase();
					JLabel tileStoryLabel = new JLabel("<HTML><div align='center'><font color='#ffffff'>" + tileStory + "</font></div></HTML>");
					tileStoryLabel.setOpaque(true);
					tileStoryLabel.setBackground(Color.decode("13056")); //DARK GREEN
					tile.add(tileStoryLabel);
				} else {
					
					tile.add(new JLabel());
					
				}
				
				tile.repaint();
				
			}
			
			
			//Remove and update all pieces
//			JLayeredPane parent = new JLayeredPane();
			
			for(int i=0; i < currentNumberOfPlayers; i++) {
				
//				parent = (JLayeredPane) playerPieces[i].getParent();
//				parent.remove(playerPieces[i]);
//				parent.repaint();
				
				tileLocations[Players.get(i).getPiecePosition()].add(playerPieces[i]);
				
			}

		}
		
		//Get mode
		switch (gameState.getGameMode()) {
		
		case SPLASH_SCREEN:
			modeSplashScreen();
			break;
		case NEW_GAME:
			modeNewGame();
			break;
		case ROLL_DIE:
			modeRollDie();
			break;
		case MOVE_PIECE:
			modeMovePiece();
			break;
		case TILE_RESULTS:
			modeTileResults();
			break;
		case END_TURN:
			modeEndTurn();
			break;
		case BUILD:
			modeBuild();
			break;
		case END_GAME:
			modeEndGame();
			break;
		case ERROR:
			modeError();
			break;
		case INITIALIZE:
			modeInitialize();
			break;
			
		}

		mainPane.revalidate();
		
	}
	


	/**
	 * This is the method that updates the players' owned buildings
	 */
	public void updatePlayerBuildings() {
		
		// Create a list of coordinates so that the areas are added in order
		String[] coords = new String[36];
		coords[0] = "0, 0, 1, 0";
		coords[9] = "2, 0, 3, 0";
		coords[18] = "2, 3, 3, 3";		
		coords[27] = "0, 3, 1, 3"; //corresponds to homebase tile number
		
		for(int i=0; i < currentNumberOfPlayers; i++) {
			
			Player p = Players.get(i);
			
			int padding = 8; //Keeps track of how much needs to be padded
			
			JPanel indivPlayerBuilding = new JPanel();
			indivPlayerBuilding.setLayout(new GridLayout(2,4));
			indivPlayerBuilding.setOpaque(false);
			
			for(Building b : p.getBuildingsOwned()) {
				
				indivPlayerBuilding.add(new JLabel(new ImageIcon(imageDir + b.getImageFile())));
				padding--;
				
			}
			
			//Pad out the empty space
			while(padding > 0) {
				
				indivPlayerBuilding.add(new JLabel());
				padding--;
				
			}
			
			displayArea.add(indivPlayerBuilding, coords[p.getHomeBase()]);
		
		}
		
		
		
	}
	
	


	/*****************************************************
	/*   Game Mode Changing Methods         
	/*   
	/*   e.g. 
	/*****************************************************/
	
	private void modeInitialize() {
		// TODO Auto-generated method stub
		gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
		
		//Rebuild tile data and repaint
		resetMainPane();
		
		update(gameState);
		
	}

	/**
	 * This is the method that displays an error
	 */
	private void modeError() {
		// TODO Auto-generated method stub
		
		JOptionPane.showMessageDialog(getParent(), "An error has occurred: \n" + gameState.getOutput());
		
		gameState = logic.execute(new Message(GameState.GameMode.RESUME, null));
		
		update(gameState);
		
	}
	

	/**
	 * MODE: SPLASH_SCREEN
	 * 
	 * This is the method displays the splash screen with button options
	 */
	public void modeSplashScreen() {
		

		//this.setLayeredPane(getSplashScreen());
		getFramePane().removeAll();
		getFramePane().repaint();
		
		getFramePane().add(getMenu(), "0, 0");
		getFramePane().add(getSplashScreen(), "0, 1");
		
		displayHelp();
		
		
	
	}
	
	
	/**
	 * MODE: NEW_GAME
	 * 
	 * This is the method displays the splash screen with button options
	 */
	public void modeNewGame() {
		
		//Create radio buttons for the players
		JPanel[] radioPanels = new JPanel[totalPlayers];
		final ButtonGroup[] bgroups = new ButtonGroup[totalPlayers];
		final JRadioButton[] humanButtons = new JRadioButton[totalPlayers];
		final JRadioButton[] aiButtons = new JRadioButton[totalPlayers];
		final JRadioButton[] noneButtons = new JRadioButton[totalPlayers];
		final JRadioButton[] difficultyButtons = new JRadioButton[3];
		
		//Difficulty Panel
		difficultyButtons[0] = new JRadioButton("Easy"  , false);
		difficultyButtons[1] = new JRadioButton("Normal"  , true);
		difficultyButtons[2] = new JRadioButton("Hard"  , false);
		
		ButtonGroup difficultygroup = new ButtonGroup();
		difficultygroup.add(difficultyButtons[0]);
		difficultygroup.add(difficultyButtons[1]);
		difficultygroup.add(difficultyButtons[2]);
		
		JPanel difficultyPanel = new JPanel();
		difficultyPanel.setLayout(new GridLayout(1, 3));
		
		Border tbdr = BorderFactory.createTitledBorder("AI Difficulty");
		Border ebdr = BorderFactory.createEmptyBorder(0, 0, 10, 0);
		Border bdr = BorderFactory.createCompoundBorder(tbdr, ebdr);
		difficultyPanel.setBorder(bdr);
		
		difficultyPanel.add(difficultyButtons[0]);
		difficultyPanel.add(difficultyButtons[1]);
		difficultyPanel.add(difficultyButtons[2]);
		
		//Create text field for the player names
		final JTextField[] playerNames = new JTextField[totalPlayers];
		
		//Submit button		
		JButton done = new JButton(new ImageIcon(imageDir + "startgame.png"));
	
		//Reset the main panes
		getFramePane().removeAll();
		getFramePane().repaint();
		
		getFramePane().add(getMenu(), "0, 0");
		getFramePane().add(getMainPane(), "0, 1");
		
		displayArea.removeAll();
		displayArea.repaint();
		
		
		//Initialize the arrays for one set of radio components per player
		for (int i=0;i<totalPlayers;i++) {
			
			playerNames[i] = new JTextField();
			bgroups[i] = new ButtonGroup();
	
			radioPanels[i] = new JPanel();
			radioPanels[i].setLayout(new GridLayout(1, 3));
			
			humanButtons[i]   = new JRadioButton("Human"  , false);
			aiButtons[i]    = new JRadioButton("AI"   , false);
			noneButtons[i] = new JRadioButton("None", true);
			
			bgroups[i].add(humanButtons[i]);
			bgroups[i].add(aiButtons[i]);
			bgroups[i].add(noneButtons[i]);
			
			radioPanels[i].add(humanButtons[i]);
			radioPanels[i].add(aiButtons[i]);
			radioPanels[i].add(noneButtons[i]);
			
			radioPanels[i].setBorder(BorderFactory.createEtchedBorder());
			
			
		}

		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.2, TableLayout.FILL, 0.2},
		 {0.1, 0.1, TableLayout.FILL, 0.2}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		JPanel playerInputList = new JPanel();
		playerInputList.setLayout(new GridLayout(10,1));
		
		for (int i=0;i<totalPlayers;i++) {
			
			playerInputList.add(playerNames[i]);
			playerInputList.add(radioPanels[i]);
			
		}
		
		playerInputList.add(difficultyPanel);
		
		done.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Holds player information in pairs of [playerType, name, playerType, name ...]
				String[] playerInformation = new String[totalPlayers*2+1];
				
				//Check for all NONE situation
				boolean allEmpty = true;
				for (int i=0;i<totalPlayers;i++) {
					
					if (noneButtons[i].isSelected() == false) {
						allEmpty = false;
					}
					
				}
				
				//Flag for proper player names
				boolean playerNamesOk = true;
				
				//Gather info and form message.			
				for (int i=0;i<totalPlayers;i++) {
					
					if (humanButtons[i].isSelected()) {
						
						playerInformation[i*2] = "Human";
						
						if((playerNames[i].getText() == null) || (playerNames[i].getText().equals(""))) {
							JOptionPane.showMessageDialog(getParent(), "Please input a name for Player " + (i+1));
							playerNamesOk = false;
						} else {
							playerInformation[i*2+1] = playerNames[i].getText(); //TODO Sanitize the player name to remove symbols
						}
						
					} else if (aiButtons[i].isSelected()) {
						playerInformation[i*2] = "AI";
						playerInformation[i*2+1] = null;
					} else {
						playerInformation[i*2] = null;
						playerInformation[i*2+1] = null;
					}
					
				}
				
				//Add difficulty information
				if (difficultyButtons[0].isSelected()) {
					playerInformation[totalPlayers*2] = new String("EASY");
				} else if (difficultyButtons[1].isSelected()) {
					playerInformation[totalPlayers*2] = new String("NORMAL");
				} else {
					playerInformation[totalPlayers*2] = new String("HARD");
				}
				
				//If not all empty, perform initialization
				
				if(allEmpty) {
					
					JOptionPane.showMessageDialog(getParent(), "Please select at least ONE player.");
					
				} else if(playerNamesOk) {
				
				
					//Execute and update
					gameState = logic.execute(new Message(GameState.GameMode.INITIALIZE, playerInformation));
					
					//Initialize player pieces
					Players = gameState.getPlayers();
					
					currentNumberOfPlayers = Players.size();
					
					for (int i=0; i < currentNumberOfPlayers; i++) {					
						playerPieces[i] = new JLabel(new ImageIcon(imageDir + Players.get(i).getPieceFileName()));
							tileLocations[Players.get(i).getPiecePosition()].add(playerPieces[i]);
					}
					
					
					update(gameState);
				
				}
		
				
			}
		});
		
		playerInputList.add(done);
		
		getNotificationLabel().setText("<HTML><font size='4'>Please enter the players' names, players' type and AI difficulty.</font></HTML>");
		
		displayArea.add(playerInputList, "1, 2, 1, 3");
		displayArea.add(getNotificationLabel(), "1, 1");

	}
	
	
	/**
	 * MODE: ROLL_DIE
	 * 
	 * This is the method displays the roll die screen to allow players to roll the dice
	 */
	public void modeRollDie() {
		
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		getNotificationLabel().setText(gameState.getOutput());
		
		//Activate die
		getRollDie().setEnabled(true);
		
		//Update playerStats and add
		updatePlayerStats();
		updatePlayerBuildings();
		
		displayArea.add(getPlayerStats(), "0, 1, 3, 1");
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		displayArea.add(getRollDie(), "3, 2");
		
		//Sets new Swing Timer
		timer = new Timer(100, new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Repaints with new random dice image and increment steps
				getRollDie().setIcon(diceImages[randomGenerator.nextInt(6)]);
				getRollDie().repaint();
				steps++;
				
				//Performs action after 15 repaints, stops timer and reset steps to 0
				if (steps == 15) {
					steps = 0;
					timer.stop();
					
					gameState = logic.execute(new Message(GameState.GameMode.ROLL_DIE, null));
					update(gameState);
					
				}
				
			}
		});
		
		//Auto roll if AI
		if(logic.getAI(gameState.getCurrentPlayer()) != null) {
			
			timer.start();
			
		}
		
		rollDie.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e1) {
				
				//Rolls die!			
				timer.start();
							
				
			}
		});
		
		
		
		
	}
	
	private void modeMovePiece() {
		// TODO Auto-generated method stub
		
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		getNotificationLabel().setText(gameState.getOutput());	
		
		//Deactivate dice button and show die roll
		getRollDie().setEnabled(false);
		displayArea.remove(getRollDie());
		
		int dieRoll = (gameState.getMovementActivityPoints() - 2);
		
		JPanel dieDisplay = new JPanel(new GridLayout(1,2));
		dieDisplay.setBackground(Color.gray);
		JLabel die1 = new JLabel(diceImages[5]);
		JLabel die2 = new JLabel(diceImages[dieRoll % 6]);
		dieDisplay.setOpaque(true);
		
		if(dieRoll > 5) {
			dieDisplay.add(die1);
			dieDisplay.add(die2);
		} else {
			dieDisplay.add(die2);
		}
		
		displayArea.add(dieDisplay, "3, 2");
		displayArea.repaint();
		
		//Update playerStats and add
		updatePlayerStats();
		updatePlayerBuildings();
		
		displayArea.add(getPlayerStats(), "0, 1, 3, 1");
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		

		
		ArrayList<Integer> possibleTileNumbers = gameState.getTilesYouCanMoveTo();
		
		for (Integer n : possibleTileNumbers) {
			
			final Integer temp = n;
			
			//Testing overlay insert
			final ImageIcon icon= new ImageIcon(imageDir + "movementpiece.png");
			
			JButton dot = new JButton(icon);
			
//			JButton dot = new JButton() {
//
//				private static final long serialVersionUID = 1L;
//				
//				protected void paintComponent(Graphics g)
//				{
//					 Graphics2D g2d = (Graphics2D) g;
//					
//					//  Display image at at full size
//					//g.drawImage(icon.getImage(), 0, 0, null);
//	 
//					//  Scale image to size of component
//					Dimension d = getSize();
//					
//					
//					
//					g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));  
//					
//					g2d.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
//	 
//					//  Fix the image position in the scroll pane
//					//Point p = scrollPane.getViewport().getViewPosition();
//					//g.drawImage(icon.getImage(), p.x, p.y, null);
//	 
//					super.paintComponent(g2d);
//				}
//				
//			};

			dot.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					//Package the input
					String[] args = new String[1];
					args[0] = "" + temp;

					//Send input to logic!
					gameState = logic.execute(new Message(GameState.GameMode.MOVE_PIECE, args));
					
					update(gameState);				
					
				}
			});
			
			tileLocations[n].add(dot);
			
		}
		
		
	}
	
	private void modeTileResults() {
		// TODO Auto-generated method stub
		
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		getNotificationLabel().setText(gameState.getOutput());
		getRollDie().setEnabled(false);
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		
		//Set Next button
		JButton next = new JButton("End Turn");
		
		next.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Send input to logic!
//				if(gameState.getCurrentPlayer().getName().equals("AI~")) {
					//TODO switch modes base do human/AI
					gameState = logic.execute(new Message(GameState.GameMode.END_TURN, null));
//				} else {
//					gameState = logic.execute(new Message(GameState.GameMode.END_TURN, null));
//				}
//				
				update(gameState);				
				
			}
		});
		
		//Update playerStats and add
		updatePlayerStats();
		updatePlayerBuildings();
		
		displayArea.add(getPlayerStats(), "0, 1, 3, 1");
		
		displayArea.add(next, "3 ,2");
		
	}
	
	
	
	private void modeBuild() {
		// TODO Auto-generated method stub
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea for buildings display
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		//Display Buildings panel
		JPanel buildingsPanel = new JPanel();
		buildingsPanel.setLayout(new GridLayout(1, 4));
		buildingsPanel.setOpaque(false);
		
		
		ArrayList<Building> buildingsYouCanBuild = gameState.getBuildingsYouCanBuild();
		ArrayList<Building> allBuildingsAvailableForBuilding = gameState.getAllBuildingsAvailableForBuilding();
		
		for (final Building b : allBuildingsAvailableForBuilding){
			//Create new pane for each building description.
			final ImageIcon icon = new ImageIcon(imageDir + "playerstat.png");
			
			JPanel indivBuildingPanel = new JPanel() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;
				
				protected void paintComponent(Graphics g)
				{
					 Graphics2D g2d = (Graphics2D) g;
					
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					
					
					
					//g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));  
					
					g2d.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g2d);
				}
				
			};
			indivBuildingPanel.setLayout(new GridLayout(3, 1));
			indivBuildingPanel.setOpaque(false);
			
			//Create corresponding button
			JButton buildButton = new JButton("BUILD IT");
			
			buildButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					
					//Send input to logic!
					String[] args = new String[1];
					args[0] = b.getName();
					gameState = logic.execute(new Message(GameState.GameMode.BUILD, args));
					
					update(gameState);				
					
				}
			});
			
			Border bdr = BorderFactory.createEmptyBorder(15, 15, 15, 15);
			indivBuildingPanel.setBorder(bdr);
			
			indivBuildingPanel.add(new JLabel(new ImageIcon (imageDir + b.getImageFile())));
			
			//Add resource requirements
			BuildingRequirement[] requirements = b.getBuildingRequirementList();
			
			JPanel resourceNeededPanel = new JPanel();
			resourceNeededPanel.setLayout(new GridLayout(10,1));
			resourceNeededPanel.setOpaque(false);
			
			resourceNeededPanel.add(new JLabel("<HTML><u>" + b.getName() + "</u></HTML>"));
			
			for(BuildingRequirement rq : requirements) {
				
				resourceNeededPanel.add(new JLabel(rq.getResources().toString() + ": " + rq.getAmount()));
				
			}
			
			resourceNeededPanel.add(new JLabel());
			
			resourceNeededPanel.add(new JLabel("No. left: " + b.getNumberOfBuildingsAvailable()));
			
			resourceNeededPanel.add(new JLabel("<HTML><font='10'>Points: " + b.getPoints() + "</font></HTML>"));
			
			indivBuildingPanel.add(resourceNeededPanel);
			indivBuildingPanel.add(buildButton);
			
			//Check if can build, if yes, enable button. If not, it is grayed out
			buildButton.setEnabled(false);
			
			for (Building b2 : buildingsYouCanBuild) {
				if (b2.getName().equals(b.getName())){
					buildButton.setEnabled(true);
				}
			}
			
			buildingsPanel.add(indivBuildingPanel);
		}
		
		displayArea.add(buildingsPanel, "0, 0, 3, 1");
		
		//Use notification to display current user's resources
		String currentUserResources = new String();
		Player p = gameState.getCurrentPlayer();
		
		for (Player.Resource r : Player.Resource.values()) {
			
			currentUserResources = currentUserResources + r.toString() + ": " + p.getCurrentResourceAmount(r) + " ";
			
		}
		
		getNotificationLabel().setText("You have " + currentUserResources);
		
		getRollDie().setEnabled(false);
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		
		//Create move on button
		JButton doneButton = new JButton("I'M DONE");
		
		doneButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Send input to logic!
				gameState = logic.execute(new Message(GameState.GameMode.BUILD, null));
				
				update(gameState);				
				
			}
		});
		
		displayArea.add(doneButton, "3, 2");
		
		
		
	}

	private void modeEndTurn() {
		// TODO Auto-generated method stub
		
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		getNotificationLabel().setText("<HTML>" + gameState.getOutput() + "</HTML>");
		getRollDie().setEnabled(false);
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		
		//Set EndTurn button
		JButton next = new JButton("End Turn");
		
		next.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Send input to logic!
				gameState = logic.execute(new Message(GameState.GameMode.END_TURN, null));
				
				update(gameState);				
				
			}
		});
		
		//Update playerStats and add
		updatePlayerStats();
		updatePlayerBuildings();
		
		displayArea.add(getPlayerStats(), "0, 1, 3, 1");
		
		displayArea.add(next, "3 ,2");
		
	}

	private void modeEndGame() {
		// TODO Auto-generated method stub
		
		displayArea.removeAll();
		displayArea.repaint();
		
		//Reset layout of displayArea
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.25, 0.375, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		getNotificationLabel().setText(gameState.getOutput());
		getRollDie().setEnabled(false);
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		
		//Set EndTurn button
		JButton next = new JButton("New Game");
		
		next.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				
				//Send input to logic!
				gameState = logic.execute(new Message(GameState.GameMode.NEW_GAME, null));
				
				update(gameState);				
				
			}
		});
		
		//Update playerStats and add
		updatePlayerStats();
		updatePlayerBuildings();
		
		displayArea.add(getPlayerStats(), "0, 1, 3, 1");
		
		displayArea.add(next, "3 ,2");
		
	}
	
	/** Shows the buildings and requirements */
	
	private void modeBuildList() {
		// TODO Auto-generated method stub
		displayArea.removeAll();
		
		//Reset layout of displayArea for buildings display
		
		double size[][] =
        {{0.25, 0.25, 0.25, 0.25},
		 {0.15, TableLayout.FILL, 0.125, 0.25}}; 
		
		displayArea.setLayout(new TableLayout(size));
		
		//Display Buildings panel
		JPanel buildingsPanel = new JPanel();
		buildingsPanel.setLayout(new GridLayout(1, 4));
		buildingsPanel.setOpaque(false);
		
		ArrayList<Building> allBuildingsAvailableForBuilding = gameState.getAllBuildingsAvailableForBuilding(); 
		
		for (final Building b : allBuildingsAvailableForBuilding){

			//Create new pane for each building description.
			final ImageIcon icon = new ImageIcon(imageDir + "playerstat.png");
			
			JPanel indivBuildingPanel = new JPanel() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;
				
				protected void paintComponent(Graphics g)
				{
					 Graphics2D g2d = (Graphics2D) g;
					
					//  Display image at at full size
					//g.drawImage(icon.getImage(), 0, 0, null);
	 
					//  Scale image to size of component
					Dimension d = getSize();
					
					
					
					//g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));  
					
					g2d.drawImage(icon.getImage(), 0, 0, d.width, d.height, null);
	 
					//  Fix the image position in the scroll pane
					//Point p = scrollPane.getViewport().getViewPosition();
					//g.drawImage(icon.getImage(), p.x, p.y, null);
	 
					super.paintComponent(g2d);
				}
				
			};
			indivBuildingPanel.setLayout(new GridLayout(2, 1));
			indivBuildingPanel.setOpaque(false);
			
			Border bdr = BorderFactory.createEmptyBorder(15, 15, 15, 15);
			indivBuildingPanel.setBorder(bdr);
			
			indivBuildingPanel.add(new JLabel(new ImageIcon (imageDir + b.getImageFile())));
			
			//Add resource requirements
			BuildingRequirement[] requirements = b.getBuildingRequirementList();
			
			JPanel resourceNeededPanel = new JPanel();
			resourceNeededPanel.setLayout(new GridLayout(10,1));
			resourceNeededPanel.setOpaque(false);
			
			resourceNeededPanel.add(new JLabel("<HTML><u>" + b.getName() + "</u></HTML>"));
			
			for(BuildingRequirement rq : requirements) {
				
				resourceNeededPanel.add(new JLabel(rq.getResources().toString() + ": " + rq.getAmount()));
				
			}
			
			resourceNeededPanel.add(new JLabel());
			
			resourceNeededPanel.add(new JLabel("No. left: " + b.getNumberOfBuildingsAvailable()));
			
			resourceNeededPanel.add(new JLabel("<HTML><font='10'>Points: " + b.getPoints() + "</font></HTML>"));
			
			indivBuildingPanel.add(resourceNeededPanel);
			
			buildingsPanel.add(indivBuildingPanel);
		}
		
		displayArea.add(buildingsPanel, "0, 1, 3, 1");
		
		//Use notification to display current user's resources
		String currentUserResources = new String();
		Player p = gameState.getCurrentPlayer();
		
		for (Player.Resource r : Player.Resource.values()) {
			
			currentUserResources = currentUserResources + r.toString() + ": " + p.getCurrentResourceAmount(r) + " ";
			
		}
		
		getNotificationLabel().setText("You have " + currentUserResources);
		getNotificationLabel().repaint();
		
		displayArea.add(getNotificationLabel(), "0, 2, 2, 2");
		
		//Create move on button
		JButton doneButton = new JButton("CLOSE");
		
		doneButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				

				update(gameState);				
				
			}
		});
		
		displayArea.add(doneButton, "3, 2");
		displayArea.revalidate();
		
	}
	
	
	

}
